package cn.easy.rest.controller;

import cn.easy.api.*;
import cn.easy.common.pojo.DataViewPojo;
import cn.easy.common.pojo.EasyResult;
import cn.easy.common.pojo.SensorType;
import cn.easy.common.pojo.TriggerCondtion;
import cn.easy.common.util.ExceptionUtil;
import cn.easy.mapper.DataMapper;
import cn.easy.pojo.*;
import cn.easy.rest.dao.JedisClient;
import cn.easy.rest.util.UserKeyUtil;
import cn.easy.vo.SensorVo;
import cn.easy.vo.SwitchVo;
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement;
import com.alibaba.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 数据控制层
 *
 * @author 谢子豪
 * @time 2017/10/6
 * @description
 */
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping("/data")
@Controller
public class DataController {
    @Autowired
    private JedisClient jedisClient;
    @Reference
    private ActionService actionService;
    @Reference
    private DataService dataService;
    @Reference
    private SensorService sensorService;
    @Reference
    private TriggerService triggerService;
    @Reference
    private DeviceService deviceService;

    private static final String SWITCH_FLAG = "EASY_SWITCH_";
    private static final String FLAG = "EASY_TRIGGRT_";

    /**
     * 检查时间 如果只写了日期的把时间给加上
     *
     * @param line
     * @return
     */
    private String checkDate(String line) {
        if (line.indexOf("-") == -1) {
            line = line.replaceAll(" ", "") + "-1-1";
        }
        if (line.indexOf(":") == -1) {
            line = line.replaceAll(" ", "") + " 0:0:0";
        }
        return line;
    }

    /**
     * 新增一条传感器数据记录
     *
     * @param map
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/insertData", method = RequestMethod.POST)
    public EasyResult insertData(@RequestBody Map map, HttpServletRequest request) {

        String userKey = null;
        ObjectMapper objectMapper = new ObjectMapper();
        Data data = new Data();

        try {
            userKey = deviceGetUserKey(request);
        } catch (Exception e) {
            e.printStackTrace();
            return EasyResult.fail(e.getMessage());
        }
       /* String deviceKey = request.getHeader("deviceKey");
        if (deviceKey == null) {
            userKey = UserKeyUtil.getUserInfoFromToken(request, jedisClient);
        } else {
            try {
                User user = deviceService.getUserByDeviceKey(deviceKey);
                userKey = user.getUserKey();
            } catch (Exception e) {
                e.printStackTrace();
                return EasyResult.fail(e.getMessage());
            }
        }*/

        /*-------判断必要的参数--------*/
        /*if (map.containsKey("userKey")) userKey = map.get("userKey").toString();
        else {
            userKey = UserKeyUtil.getUserInfoFromToken(request, jedisClient);
            if (StringUtils.isEmpty(userKey)) {
                return EasyResult.fail("缺少用户key");
            }
        }
        if (userKey == null) {
            return EasyResult.fail("缺少用户key");
        }*/

        if (!map.containsKey("sensorId")) return EasyResult.fail("缺少传感器编号");
        else data.setSensorId(Integer.parseInt(map.get("sensorId").toString()));

        if (!map.containsKey("sensorData")) return EasyResult.fail("数据不可以为空");
        else data.setSensorData(map.get("sensorData").toString());
        /*-------新增数据--------*/
        try {
            dataService.insertData(userKey, data);

            //对数据进行触发处理
            Sensor sensor = sensorService.searchSensorById(data.getSensorId(), userKey);

            if (sensor != null) {
                //获得所有的触发器
                String sensorData = data.getSensorData();//当前的值
                List<Easytrigger> list = triggerService.searchSensorAllTrigger(sensor.getSensorId(), userKey);

                //开关
                if (sensor.getSensorType() == SensorType.SWITCH.getIndex()) {
                    /*
                     *对于开关，首先要把最新的数据保存到 redis中
                     * 然后判断开关是否有触发触发器
                     * 由于开关 本身 不会存在数据反复触发这一问题 ，所以就不用做开关判断
                     */
                    String switchName = getSwitchName(sensor.getSensorId());
                    SwitchVo switchVo = new SwitchVo();
                    switchVo.setUserKey(userKey);
                    switchVo.setState(Integer.parseInt(sensorData));
                    String saveData = objectMapper.writeValueAsString(switchVo);
                    jedisClient.set(switchName, saveData);
                    for (Easytrigger easytrigger : list) {
                        //触发的符号只能是=
                        String number = easytrigger.getTriggerNumber();
                        if (Integer.parseInt(sensorData) == Integer.parseInt(number)) {
                            //触发开关！
                            Integer actionId = easytrigger.getActionId();
                            Action action = actionService.getActionById(actionId);
                            if (action != null) {
                                System.out.println("触发执行动作" + action.getActionDesc());
                            } else {
                                System.out.println("动作找不到");
                            }
                        }
                    }

                }
                //数值型传感器
                if (sensor.getSensorType() == SensorType.NUMBER.getIndex()) {
                    /*
                    对于数值型传感器，判断出否触发
                    触发再看触发热action在redis中有没有记录
                    有就不再重复触发，没有触发并在redis中标记
                    */
                    for (Easytrigger easytrigger : list) {
                        Integer condition = easytrigger.getTriggerCondition();
                        //临界值
                        String number = easytrigger.getTriggerNumber();


                        if (checkConditionToNumber(condition, sensorData, number)) {
                            Action action = actionService.getActionById(easytrigger.getActionId());
                            if (action != null) {
                                String exit = jedisClient.get(getName(easytrigger.getTriggerId()));
                                if (exit == null) {
                                    System.out.println("触发动作:" + action.getActionDesc());
                                    jedisClient.set(getName(easytrigger.getTriggerId()), 1 + "");
                                }

                            } else {
                                System.out.println("动做不存在");
                            }
                        } else {
                            //数据正常移除开关
                            if (jedisClient.get(getName(easytrigger.getTriggerId())) != null) {
                                System.out.println("开关移除" + easytrigger.getTriggerId());
                                jedisClient.del(getName(easytrigger.getTriggerId()));
                            }
                        }
                    }
                }
                //GPS
                if (sensor.getSensorType() == SensorType.GPS.getIndex()) {
                    /*
                     * 对于GPS 首先按照#取出经度 维度  半径
                     * 然后做比较判断是否触发
                     * */
                    //获取上传数据的经度 维度 半径
                    String[] split = sensorData.split("#");
                    Float longtitude = Float.parseFloat(split[0]);
                    Float dimension = Float.parseFloat(split[1]);

                    for (Easytrigger easytrigger : list) {
                        Integer triggerCondition = easytrigger.getTriggerCondition();
                        //拿到触发的边缘值
                        String triggerNumber = easytrigger.getTriggerNumber();
                        String[] conditionSplit = triggerNumber.split("#");
                        Float condtionLongtitude = Float.parseFloat(conditionSplit[0]);
                        Float condtionDimension = Float.parseFloat(conditionSplit[1]);
                        Float condtionRadius = Float.parseFloat(conditionSplit[2]);
                        //圈外触发
                        boolean in = (triggerCondition == TriggerCondtion.LESS.getIndex() ||
                                triggerCondition == TriggerCondtion.EQUAL.getIndex() ||
                                triggerCondition == TriggerCondtion.LESSEQUAL.getIndex())
                                && isGpsIn(longtitude, dimension, condtionLongtitude, condtionDimension, condtionRadius);
                        //圈内触发
                        boolean out = (triggerCondition == TriggerCondtion.GREATHER.getIndex() ||
                                triggerCondition == TriggerCondtion.GREATHEREQUAL.getIndex()) && (!isGpsIn(longtitude, dimension, condtionLongtitude, condtionDimension, condtionRadius));

                        //触发
                        String name = getName(easytrigger.getTriggerId());
                        if (in || out) {
                            System.out.println("符合触发~+++++++++++++++============");
                            //看下redis中有没有
                            String s = jedisClient.get(name);
                            if (s == null) {
                                System.out.println("执行触发操作》");
                                jedisClient.set(name, 1 + "");
                            }
                        } else {
                            //数据正常产看有没有 redis记录，有清除
                            if (jedisClient.get(name) != null) {
                                jedisClient.del(name);
                            }
                        }
                    }
                }

            } else {
                return EasyResult.fail("没有这个传感器");
            }
            return EasyResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return EasyResult.fail(e.getMessage());
        }

    }

    /**
     * 删除一个传感器
     *
     * @param dataId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/deleteData/{dataId}", method = RequestMethod.GET)
    public EasyResult deleteData(@PathVariable int dataId, HttpServletRequest request) {
        try {
            String userKey = deviceGetUserKey(request);
            dataService.deleteData(userKey, dataId);
            return EasyResult.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return EasyResult.fail(e.getMessage());
        }

    }

    /**
     * 获取一个传感器指定时间段内的全部数据,如果传感器所属于的设备是公开的可以不传userKey
     *
     * @param map
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/searchSensorDate", method = RequestMethod.POST)
    public EasyResult searchSensorDate(@RequestBody Map map, HttpServletRequest request) {
        String userKey = null;
        try {
            userKey = deviceGetUserKey(request);
        } catch (Exception e) {
            e.printStackTrace();
            return EasyResult.fail(e.getMessage());
        }
        int sensorId;//传感器编号
        Date startTime = null;//开始时间
        Date endTime = null;//结束时间
        /*--------------得要传感器编号以及userkey------------*/
        if (map.containsKey("sensorId")) sensorId = Integer.parseInt(map.get("sensorId").toString());
        else return EasyResult.fail("缺少传感器编号");


        /*--------------起始时间与结束时间------------*/
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (map.containsKey("startTime")) //起始时间
            try {
                startTime = format.parse(checkDate(map.get("startTime").toString()));
            } catch (ParseException e) {
                e.printStackTrace();
                String expDate = format.format(new Date());
                return EasyResult.fail("起始时间格式错误,请按照如下格式:" + expDate);
            }
        if (map.containsKey("endTime")) //结束时间
            try {
                endTime = format.parse(checkDate(map.get("endTime").toString()));
            } catch (ParseException e) {
                e.printStackTrace();
                String expDate = format.format(new Date());
                return EasyResult.fail("截至时间格式错误,请按照如下格式:" + expDate);
            }
        /*--------------执行查询操作------------*/
        try {
            List<DataViewPojo> list;
            if (userKey != null) list = dataService.searchSensorDate(sensorId, startTime, endTime, userKey);
            else list = dataService.searchSensorDate(sensorId, startTime, endTime);
            return EasyResult.ok(list);
        } catch (Exception e) {
            e.printStackTrace();
            return EasyResult.fail(e.getMessage());
        }


    }

    public static String getSwitchName(int sensorId) {
        return SWITCH_FLAG + sensorId;
    }

    public static String getName(int triggerId) {
        return FLAG + triggerId;
    }


    /**
     * 检查是number类型否触发
     *
     * @param type      比较标识
     * @param number    当前数据
     * @param conNumber 临界数据
     * @return
     */
    public static boolean checkConditionToNumber(int type, String number, String conNumber) {
        //>
        if (type == TriggerCondtion.GREATHER.getIndex()) {
            if (Float.parseFloat(number) > Float.parseFloat(conNumber)) return true;
            else return false;
        }
        //=
        if (type == TriggerCondtion.EQUAL.getIndex()) {
            if (Float.parseFloat(number) == Float.parseFloat(conNumber)) return true;
            else return false;
        }
        //>=
        if (type == TriggerCondtion.GREATHEREQUAL.getIndex()) {
            if (Float.parseFloat(number) >= Float.parseFloat(conNumber)) return true;
            else return false;
        }
        //<
        if (type == TriggerCondtion.LESS.getIndex()) {
            if (Float.parseFloat(number) < Float.parseFloat(conNumber)) return true;
            else return false;
        }
        //<=
        if (type == TriggerCondtion.LESSEQUAL.getIndex()) {
            if (Float.parseFloat(number) <= Float.parseFloat(conNumber)) return true;
            else return false;
        }
        return false;
    }

    /**
     * GPS类型传感器的 临界值判定 计算当前坐标在圈内还是圈外，圈内返回true
     *
     * @param longtitude         当前的经度
     * @param dimension          当前的维度
     * @param condtionLongtitude 临界的经度
     * @param condtionDimension  临界的维度
     * @param condtionRadius     临界的半径
     * @return
     */
    public static boolean isGpsIn(Float longtitude, Float dimension,
                                  Float condtionLongtitude, Float condtionDimension, Float condtionRadius) {
        /*
         * 计算在圈内还是圈外的方法是
         * 两个圆心，及两个经纬度坐标计算距离=r，在和圆的半径condtionRadius比较
         * 如果r>condtionRadius 圈外  else  圈内
         * */
        double r = Math.sqrt(Math.pow(condtionLongtitude - longtitude, 2) + Math.pow(condtionDimension - dimension, 2));

        if (r <= condtionRadius) return true;
        else return false;
    }

    /**
     * device  拿到userKey 的特殊处理
     * 有deviceId 我们就直接使用deviceId 去获取userKey
     * 没有 利用getUserInfoFromToken 去拿到userKey
     *
     * @param request
     * @return
     * @throws Exception
     */
    private String deviceGetUserKey(HttpServletRequest request) throws Exception {
        String userKey = null;
        ObjectMapper objectMapper = new ObjectMapper();
        Data data = new Data();

        String deviceKey = request.getHeader("deviceKey");
        if (deviceKey == null) {
            userKey = UserKeyUtil.getUserInfoFromToken(request, jedisClient);
        } else {

            User user = deviceService.getUserByDeviceKey(deviceKey);
            userKey = user.getUserKey();

        }
        return userKey;
    }


}
